import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, FindOptionsWhere, Between } from 'typeorm';
import { BaseService } from '../../../common/services/base.service';
import { SecurityLog, SecurityEventType, SecurityLevel } from '../entities/security-log.entity';
import { CreateSecurityLogDto } from '../dto/create-security-log.dto';
import { QuerySecurityLogDto } from '../dto/query-security-log.dto';
import { UpdateSecurityLogDto } from '../dto/update-security-log.dto';
import { PaginationResponseDto } from '../../../common/dto/pagination.dto';

@Injectable()
export class SecurityLogService extends BaseService<SecurityLog> {
  private readonly logger = new Logger(SecurityLogService.name);

  constructor(
    @InjectRepository(SecurityLog)
    private readonly securityLogRepository: Repository<SecurityLog>,
  ) {
    super(securityLogRepository);
  }

  /**
   * 创建安全日志
   */
  async createSecurityLog(createDto: CreateSecurityLogDto): Promise<SecurityLog> {
    try {
      const securityLog = this.securityLogRepository.create(createDto);
      const result = await this.securityLogRepository.save(securityLog);
      
      this.logger.log(`安全日志创建成功: ${result.id} - ${result.eventTitle}`);
      return result;
    } catch (error) {
      this.logger.error(`创建安全日志失败: ${error.message}`, error.stack);
      throw error;
    }
  }

  /**
   * 分页查询安全日志
   */
  async findSecurityLogsWithPagination(
    queryDto: QuerySecurityLogDto,
  ): Promise<PaginationResponseDto<SecurityLog>> {
    const { page = 1, pageSize = 10, sortBy, sortOrder = 'DESC' } = queryDto;

    const queryBuilder = this.securityLogRepository
      .createQueryBuilder('securityLog')
      .where('securityLog.isDeleted = :isDeleted', { isDeleted: false });

    // 添加查询条件
    if (queryDto.eventType) {
      queryBuilder.andWhere('securityLog.eventType = :eventType', { eventType: queryDto.eventType });
    }

    if (queryDto.securityLevel) {
      queryBuilder.andWhere('securityLog.securityLevel = :securityLevel', { securityLevel: queryDto.securityLevel });
    }

    if (queryDto.eventTitle) {
      queryBuilder.andWhere('securityLog.eventTitle LIKE :eventTitle', { eventTitle: `%${queryDto.eventTitle}%` });
    }

    if (queryDto.userId) {
      queryBuilder.andWhere('securityLog.userId = :userId', { userId: queryDto.userId });
    }

    if (queryDto.username) {
      queryBuilder.andWhere('securityLog.username LIKE :username', { username: `%${queryDto.username}%` });
    }

    if (queryDto.ipAddress) {
      queryBuilder.andWhere('securityLog.ipAddress = :ipAddress', { ipAddress: queryDto.ipAddress });
    }

    if (queryDto.requestUrl) {
      queryBuilder.andWhere('securityLog.requestUrl LIKE :requestUrl', { requestUrl: `%${queryDto.requestUrl}%` });
    }

    if (queryDto.requestMethod) {
      queryBuilder.andWhere('securityLog.requestMethod = :requestMethod', { requestMethod: queryDto.requestMethod });
    }

    if (queryDto.apiName) {
      queryBuilder.andWhere('securityLog.apiName LIKE :apiName', { apiName: `%${queryDto.apiName}%` });
    }

    if (queryDto.errorCode) {
      queryBuilder.andWhere('securityLog.errorCode = :errorCode', { errorCode: queryDto.errorCode });
    }

    if (queryDto.httpStatusCode) {
      queryBuilder.andWhere('securityLog.httpStatusCode = :httpStatusCode', { httpStatusCode: queryDto.httpStatusCode });
    }

    if (queryDto.isHandled !== undefined) {
      queryBuilder.andWhere('securityLog.isHandled = :isHandled', { isHandled: queryDto.isHandled });
    }

    if (queryDto.handledBy) {
      queryBuilder.andWhere('securityLog.handledBy = :handledBy', { handledBy: queryDto.handledBy });
    }

    // 时间范围查询
    if (queryDto.startTime || queryDto.endTime) {
      const startTime = queryDto.startTime ? new Date(queryDto.startTime) : new Date(0);
      const endTime = queryDto.endTime ? new Date(queryDto.endTime) : new Date();
      queryBuilder.andWhere('securityLog.createdAt BETWEEN :startTime AND :endTime', { startTime, endTime });
    }

    // 添加排序
    if (sortBy) {
      queryBuilder.orderBy(`securityLog.${sortBy}`, sortOrder);
    } else {
      queryBuilder.orderBy('securityLog.createdAt', sortOrder);
    }

    // 分页
    queryBuilder.skip((page - 1) * pageSize).take(pageSize);

    const [data, total] = await queryBuilder.getManyAndCount();

    return {
      data,
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize),
      hasNext: page < Math.ceil(total / pageSize),
      hasPrev: page > 1,
    };
  }

  /**
   * 更新安全日志
   */
  async updateSecurityLog(id: string, updateDto: UpdateSecurityLogDto): Promise<SecurityLog> {
    try {
      const securityLog = await this.findById(id);
      
      // 如果标记为已处理，设置处理时间
      if (updateDto.isHandled && !securityLog.isHandled) {
        updateDto.handledAt = new Date().toISOString();
      }

      Object.assign(securityLog, updateDto);
      const result = await this.securityLogRepository.save(securityLog);
      
      this.logger.log(`安全日志更新成功: ${id}`);
      return result;
    } catch (error) {
      this.logger.error(`更新安全日志失败: ${error.message}`, error.stack);
      throw error;
    }
  }

  /**
   * 批量标记为已处理
   */
  async batchMarkAsHandled(ids: string[], handledBy: string, handledNote?: string): Promise<boolean> {
    try {
      const securityLogs = await this.securityLogRepository.find({
        where: { id: ids as any, isDeleted: false } as FindOptionsWhere<SecurityLog>,
      });

      if (securityLogs.length !== ids.length) {
        return false;
      }

      for (const securityLog of securityLogs) {
        securityLog.isHandled = true;
        securityLog.handledAt = new Date();
        securityLog.handledBy = handledBy;
        if (handledNote) {
          securityLog.handledNote = handledNote;
        }
      }

      await this.securityLogRepository.save(securityLogs);
      
      this.logger.log(`批量标记安全日志为已处理成功: ${ids.length} 条记录`);
      return true;
    } catch (error) {
      this.logger.error(`批量标记安全日志失败: ${error.message}`, error.stack);
      return false;
    }
  }

  /**
   * 获取安全统计信息
   */
  async getSecurityStatistics(startTime?: Date, endTime?: Date) {
    try {
      const queryBuilder = this.securityLogRepository
        .createQueryBuilder('securityLog')
        .where('securityLog.isDeleted = :isDeleted', { isDeleted: false });

      if (startTime && endTime) {
        queryBuilder.andWhere('securityLog.createdAt BETWEEN :startTime AND :endTime', { startTime, endTime });
      }

      // 按事件类型统计
      const eventTypeStats = await queryBuilder
        .select('securityLog.eventType', 'eventType')
        .addSelect('COUNT(*)', 'count')
        .groupBy('securityLog.eventType')
        .getRawMany();

      // 按安全级别统计
      const securityLevelStats = await queryBuilder
        .select('securityLog.securityLevel', 'securityLevel')
        .addSelect('COUNT(*)', 'count')
        .groupBy('securityLog.securityLevel')
        .getRawMany();

      // 按处理状态统计
      const handledStats = await queryBuilder
        .select('securityLog.isHandled', 'isHandled')
        .addSelect('COUNT(*)', 'count')
        .groupBy('securityLog.isHandled')
        .getRawMany();

      // 获取总数
      const total = await queryBuilder.getCount();

      return {
        total,
        eventTypeStats,
        securityLevelStats,
        handledStats,
      };
    } catch (error) {
      this.logger.error(`获取安全统计信息失败: ${error.message}`, error.stack);
      throw error;
    }
  }

  /**
   * 获取高风险安全事件
   */
  async getHighRiskEvents(limit: number = 10): Promise<SecurityLog[]> {
    try {
      return await this.securityLogRepository.find({
        where: {
          securityLevel: SecurityLevel.HIGH,
          isDeleted: false,
        } as FindOptionsWhere<SecurityLog>,
        order: { createdAt: 'DESC' },
        take: limit,
      });
    } catch (error) {
      this.logger.error(`获取高风险安全事件失败: ${error.message}`, error.stack);
      throw error;
    }
  }

  /**
   * 获取未处理的安全事件
   */
  async getUnhandledEvents(limit: number = 10): Promise<SecurityLog[]> {
    try {
      return await this.securityLogRepository.find({
        where: {
          isHandled: false,
          isDeleted: false,
        } as FindOptionsWhere<SecurityLog>,
        order: { createdAt: 'DESC' },
        take: limit,
      });
    } catch (error) {
      this.logger.error(`获取未处理安全事件失败: ${error.message}`, error.stack);
      throw error;
    }
  }

  /**
   * 清理旧的安全日志
   */
  async cleanOldLogs(days: number = 90): Promise<number> {
    try {
      const cutoffDate = new Date();
      cutoffDate.setDate(cutoffDate.getDate() - days);

      const result = await this.securityLogRepository
        .createQueryBuilder()
        .update(SecurityLog)
        .set({ isDeleted: true })
        .where('createdAt < :cutoffDate', { cutoffDate })
        .andWhere('isDeleted = :isDeleted', { isDeleted: false })
        .execute();

      const deletedCount = result.affected || 0;
      this.logger.log(`清理旧安全日志成功: ${deletedCount} 条记录`);
      return deletedCount;
    } catch (error) {
      this.logger.error(`清理旧安全日志失败: ${error.message}`, error.stack);
      throw error;
    }
  }
}
